/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2008，所有权利保留。
 * 
 * 项目名：	rumba-web
 * 文件名：	CommandQueue.java
 * 模块说明：	
 * 修改历史：
 * Oct 25, 2008 - lxm - 创建。
 */
package com.hd123.rumba.gwt.util.client.commandqueue;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * 命令队列，提供顺序执行命令的能力。并可以由调用者决定在何时执行下一个命令，其中允许命令中包含RPC调用。
 * 
 * @author lxm
 * 
 */
public class CommandQueue {

  private static HashMap queueMap = new HashMap();
  public static final String QUEUENAME_DEFAULT = "__qname_default__";

  /**
   * 向默认队列中加入一个命令。
   * 
   * @param command
   *          指定被加入的队列。传入null将被忽略。
   */
  public static void offer(Command command) {
    offer(QUEUENAME_DEFAULT, command);
  }

  /**
   * 向指定的队列中加入一个命令。
   * 
   * @param name
   *          指定队列名。
   * @param command
   *          指定被加入的队列。传入null将被忽略。
   */
  public static void offer(String name, Command command) {
    if (command == null)
      return;
    CommandQueue queue = (CommandQueue) queueMap.get(name);
    if (queue == null) {
      queue = new CommandQueue(name);
      queueMap.put(name, queue);
    }
    queue.offer_(command);
  }

  /**
   * 唤醒默认队列，即如果队列尚未处于运行状态，则是其开始运行。
   */
  public static void awake() {
    awake(QUEUENAME_DEFAULT);
  }

  /**
   * 唤醒指定的队列，即如果队列尚未处于运行状态，则是其开始运行。
   * 
   * @param name
   *          指定队列名。
   */
  public static void awake(String name) {
    CommandQueue queue = (CommandQueue) queueMap.get(name);
    if (queue == null)
      return;
    if (!queue.isRunning_())
      queue.goon();
  }

  /**
   * 判断默认队列，当前是否处于运行中。
   * 
   * @return
   */
  public static boolean isRunning() {
    return isRunning(QUEUENAME_DEFAULT);
  }

  /**
   * 判断指定队列，当前是否处于运行中。
   * 
   * @param name
   *          指定队列名。
   * @return
   */
  public static boolean isRunning(String name) {
    CommandQueue queue = (CommandQueue) queueMap.get(name);
    return queue == null ? false : queue.isRunning_();
  }

  /**
   * 抽象命令接口。
   * 
   * @author lxm
   * 
   */
  public static abstract interface Command {
    // Do Nothing
  }

  private CommandQueue(String name) {
    super();
    this.name = name;
    running = false;
  }

  private String name;
  private List queue = new ArrayList();
  private boolean running;

  /**
   * 取得队列名。
   * 
   * @return
   */
  public String getName() {
    return name;
  }

  /**
   * 返回是否正在运行中。
   * 
   * @return
   */
  private boolean isRunning_() {
    return running;
  }

  /**
   * 通知队列无论队列中是否还有其它未执行的命令都中断执行。
   */
  public void abort() {
    queue.clear();
    running = false;
  }

  /**
   * 通知队列如果存在执行下一个命令。
   */
  public void goon() {
    running = false;
    Command command = poll_();
    if (command == null)
      return;

    running = true;

    if (command instanceof LocalCommand) {
      ((LocalCommand) command).onCall(this);
      return;
    }

    if (command instanceof RPCCommand) {
      Callback callback = new Callback(this, (RPCCommand) command);
      ((RPCCommand) command).onCall(this, callback);
    }
  }

  void offer_(Command command) {
    queue.add(command);
  }

  Command poll_() {
    if (queue.size() == 0)
      return null;
    Command command = (Command) queue.get(0);
    queue.remove(0);
    return command;
  }

  private static class Callback implements AsyncCallback {

    public Callback(CommandQueue queue, RPCCommand command) {
      super();
      this.queue = queue;
      this.command = command;
    }

    private CommandQueue queue;
    private RPCCommand command;

    public void onFailure(Throwable t) {
      command.onFailure(queue, t);
    }

    public void onSuccess(Object result) {
      command.onSuccess(queue, result);
    }

  }

}
